/*
 * @(#)PatientIdentityClient.java
 * Date 2013-02-20
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.pix.client;

import java.util.List;

import javax.inject.Inject;

import javax.xml.ws.BindingProvider;

import javax.xml.ws.soap.AddressingFeature;

import ihe.iti.pixv3._2007.PIXManagerPortType;
import ihe.iti.pixv3._2007.PIXManagerService;

import org.hl7.v3.ActClassControlAct;
import org.hl7.v3.CS;
import org.hl7.v3.CommunicationFunctionType;
import org.hl7.v3.EntityClassDevice;
import org.hl7.v3.MCCIIN000002UV01;
import org.hl7.v3.MCCIMT000100UV01Device;
import org.hl7.v3.MCCIMT000100UV01Receiver;
import org.hl7.v3.MCCIMT000100UV01Sender;
import org.hl7.v3.MCCIMT000200UV01Acknowledgement;
import org.hl7.v3.PRPAIN201301UV02;
import org.hl7.v3.PRPAIN201301UV02MFMIMT700701UV01ControlActProcess;
import org.hl7.v3.PRPAIN201301UV02MFMIMT700701UV01RegistrationEvent;
import org.hl7.v3.PRPAIN201301UV02MFMIMT700701UV01Subject1;
import org.hl7.v3.PRPAIN201301UV02MFMIMT700701UV01Subject2;
import org.hl7.v3.PRPAMT201301UV02Patient;
import org.hl7.v3.ParticipationTargetSubject;
import org.hl7.v3.XActMoodIntentEvent;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import us.hornerscorners.lamppost.config.EndpointConfig;
import us.hornerscorners.lamppost.hl7v3common.constant.AckSetting;

import us.hornerscorners.lamppost.hl7v3common.constant.DeterminerCode;
import us.hornerscorners.lamppost.hl7v3common.constant.HL7Constant;
import us.hornerscorners.lamppost.hl7v3common.constant.Interaction;
import us.hornerscorners.lamppost.hl7v3common.constant.ProcessingCode;
import us.hornerscorners.lamppost.hl7v3common.constant.ProcessingMood;

import us.hornerscorners.lamppost.hl7v3common.transformer.CDTransformer;
import us.hornerscorners.lamppost.hl7v3common.transformer.CSTransformer;
import us.hornerscorners.lamppost.hl7v3common.transformer.IITransformer;
import us.hornerscorners.lamppost.hl7v3common.transformer.TSTransformer;

import us.hornerscorners.lamppost.ws.AbstractWSClient;


/**
 *
 * @author jim
 */
public class PixManagerClient extends AbstractWSClient {

    /** Field description */
    @Inject
    private CDTransformer cdTransformer;

    /** Field description */
    @Inject
    private CSTransformer csTransformer;

    /** Field description */
    @Inject
    private IITransformer iiTransformer;

    /** Field description */
    private final Logger logger = LoggerFactory.getLogger(getClass());

    /** Field description */
    private final PIXManagerService service;

    /** Field description */
    @Inject
    private TSTransformer tsTransformer;

    /**
     * Constructs ...
     *
     *
     * @param config
     */
    public PixManagerClient(EndpointConfig config) {

        super(config);
        this.service = new PIXManagerService();
    }

    /**
     * Method description
     *
     * @param patient
     * @return
     */
    public boolean addPatientRecord(PRPAMT201301UV02Patient patient) {

        PRPAIN201301UV02 root = new PRPAIN201301UV02();

        root.setITSVersion(HL7Constant.ITSVersion.getCode());

        // /id
        root.setId(this.iiTransformer.createRandomII());

        // /creationTime
        root.setCreationTime(this.tsTransformer.createNowTS());

        // /interactionId

        root.setInteractionId(
            this.iiTransformer.transform(Interaction.PRPA_IN201310UV02));

        // /processingCode
        root.setProcessingCode(this.csTransformer.transform(ProcessingCode.Production));

        // /processingModeCode
        root.setProcessingModeCode(this.csTransformer.transform(ProcessingMood.CurrentProcessing));

        // /acceptAckCode
        root.setAcceptAckCode(this.csTransformer.transform(AckSetting.Always));

        // /receiver
        MCCIMT000100UV01Receiver receiver = new MCCIMT000100UV01Receiver();

        receiver.setTypeCode(CommunicationFunctionType.RCV);

        MCCIMT000100UV01Device rcvDevice = new MCCIMT000100UV01Device();

        rcvDevice.setClassCode(EntityClassDevice.DEV);
        rcvDevice.setDeterminerCode(DeterminerCode.Instance.getCode());

        rcvDevice.getId().add(this.iiTransformer.createNullFlavorII());
        receiver.setDevice(rcvDevice);

        root.getReceiver().add(receiver);

        // /sender
        MCCIMT000100UV01Sender sender = new MCCIMT000100UV01Sender();

        sender.setTypeCode(CommunicationFunctionType.SND);

        MCCIMT000100UV01Device sndDevice = new MCCIMT000100UV01Device();

        sndDevice.setClassCode(EntityClassDevice.DEV);
        sndDevice.setDeterminerCode(DeterminerCode.Instance.getCode());

        sndDevice.getId().add(this.iiTransformer.createNullFlavorII());
        sender.setDevice(sndDevice);

        root.setSender(sender);

        // /controlActProcess
        PRPAIN201301UV02MFMIMT700701UV01ControlActProcess controlActProcess =
            new PRPAIN201301UV02MFMIMT700701UV01ControlActProcess();

        controlActProcess.setClassCode(ActClassControlAct.CACT);
        controlActProcess.setMoodCode(XActMoodIntentEvent.EVN);
        root.setControlActProcess(controlActProcess);

        // /controlActProcess/code
        controlActProcess.setCode(this.cdTransformer.transform("PRPA_TE201301UV02",
                "2.16.840.1.113883.1.6"));

        // /controlActProcess/subject
        PRPAIN201301UV02MFMIMT700701UV01Subject1 subject =
            new PRPAIN201301UV02MFMIMT700701UV01Subject1();

        subject.getTypeCode().add("SUBJ");
        controlActProcess.getSubject().add(subject);

        // /controlActProcess/subject/registration
        PRPAIN201301UV02MFMIMT700701UV01RegistrationEvent registrationEvent =
            new PRPAIN201301UV02MFMIMT700701UV01RegistrationEvent();

        registrationEvent.getClassCode().add("REG");
        registrationEvent.getMoodCode().add("EVN");
        subject.setRegistrationEvent(registrationEvent);

        // /controlActProcess/subject/registrationEvent/id
        registrationEvent.getId().add(this.iiTransformer.createNullFlavorII());

        // /controlActProcess/subject/registrationEvent/statusCode
        registrationEvent.setStatusCode(this.csTransformer.transform("active"));

        // /controlActProcess/subject/registrationEvent/subject1
        PRPAIN201301UV02MFMIMT700701UV01Subject2 subject1 =
            new PRPAIN201301UV02MFMIMT700701UV01Subject2();

        subject1.setTypeCode(ParticipationTargetSubject.SBJ);
        registrationEvent.setSubject1(subject1);

        // /controlActProcess/subject/registrationEvent/patient
        subject1.setPatient(patient);

        PIXManagerPortType port =
            this.service.getPIXManagerPortSoap12(new AddressingFeature(true, true));

        configureBindingProvider(null, (BindingProvider) port);

        boolean result = false;
        MCCIIN000002UV01 response = port.pixManagerPRPAIN201301UV02(root);

        if (response != null) {

            List<MCCIMT000200UV01Acknowledgement> acks = response.getAcknowledgement();

            if (acks.isEmpty() == false) {

                CS ackcode = acks.get(0).getTypeCode();

                if (ackcode != null) {

                    result = "AA".equals(ackcode.getCode());
                }
            }
        }

        return result;
    }
}
